#include "cpublicfunc.h"

#include <iostream>
#include <fstream>
#include <ctime>
#include <chrono>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cctype>
#include <string.h>

#if defined(_WIN32) || defined(WIN32)
#include <Windows.h>
#include <direct.h>
#include <tchar.h>
#else
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#endif

namespace PubFunc {

#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif

//获取错误码具体信息
std::string CPublicFunc::getErrMsg(const int &nCode)
{
    std::string sErrMsg = "Unknow";
    switch(nCode)
    {
    case enOK:
        sErrMsg = "";
        break;
    case enFileOpenFailed:
        sErrMsg = "Open file failed.";
        break;
    case enAllocErr:
        sErrMsg = "Alloc memory failed.";
        break;

        //module manager
    case enNoDrvFile:
        sErrMsg = "No driver file.";
        break;
    case enLoadFailed:
        sErrMsg = "Load driver failed.";
        break;
    case enDrvUnload:
        sErrMsg = "Driver unload.";
        break;

        //tag manager
    case enUnknowVersion:
        sErrMsg = "Open file failed.";
        break;
    case enFirstLineEmpty:
        sErrMsg = "First line is empty.";
        break;
    case enFirstLineFormatFailed:
        sErrMsg = "First line format error.";
        break;
    case enTitleEmpty:
        sErrMsg = "File title is empty.";
        break;
    case enVerColUnknown:
        sErrMsg = "Version column unknown.";
        break;
    case enColumnMismatch:
        sErrMsg = "Column mismatch.";
        break;
    case enDuplicateName:
        sErrMsg = "Duplicate name.";
        break;

        //tag name
    case enTagEmpty:
        sErrMsg = "Tag name is empty.";
        break;
    case enTagTooLong:
        sErrMsg = "Tag name is too long.";
        break;
    case enTagFormatErr:
        sErrMsg = "Tag name format error.";
        break;
    case enTagSpecialChar:
        sErrMsg = "Tag name special characters.";
        break;

        //other
    case enUnknow:
    default:
        break;
    }
    return sErrMsg;
}

// 跨平台文件存在检查
bool CPublicFunc::file_exists(const std::string& path) {
#if defined(_WIN32) || defined(WIN32)
    DWORD attrs = GetFileAttributesA(path.c_str());
    return (attrs != INVALID_FILE_ATTRIBUTES &&
            !(attrs & FILE_ATTRIBUTE_DIRECTORY));
#else
    struct stat buffer;
    return (stat(path.c_str(), &buffer) == 0);
#endif
}

// 跨平台获取文件大小
long CPublicFunc::get_file_size(const std::string& path) {
#if defined(_WIN32) || defined(WIN32)
    WIN32_FILE_ATTRIBUTE_DATA fad;
    if (!GetFileAttributesExA(path.c_str(), GetFileExInfoStandard, &fad))
        return -1;
    return fad.nFileSizeLow;
#else
    struct stat stat_buf;
    if (stat(path.c_str(), &stat_buf) != 0) return -1;
    return stat_buf.st_size;
#endif
}

// 跨平台路径分隔符处理
std::string CPublicFunc::extract_filename(const std::string& path) {
    auto pos = path.find_last_of("/\\");
    return (pos == std::string::npos) ? path : path.substr(pos + 1);
}

// 跨平台URL编码实现
std::string CPublicFunc::url_encode(const std::string &s) {
    const char hex[] = "0123456789ABCDEF";
    std::string encoded;
    encoded.reserve(s.size() * 3);

    for (auto c : s)
    {
        if (isalnum((unsigned char)c)) encoded.push_back(c);
        else
        {
            encoded.push_back('%');
            encoded.push_back(hex[(c >> 4) & 0xF]);
            encoded.push_back(hex[c & 0xF]);
        }
    }

    return encoded;
}

// 跨平台目录创建
bool CPublicFunc::create_directories(const std::string& path) {
#if defined(_WIN32) || defined(WIN32)
    return _mkdir(path.c_str()) == 0 || errno == EEXIST;
#else
    return mkdir(path.c_str(), 0755) == 0 || errno == EEXIST;
#endif
}

// 跨平台文件读取
bool CPublicFunc::read_file(const std::string& path, std::string& out) {
    std::ifstream fs(path, std::ios::binary);
    if (!fs) return false;

    fs.seekg(0, std::ios::end);
    auto size = fs.tellg();
    if (size <= 0) return false;

    out.resize(static_cast<size_t>(size));
    fs.seekg(0);
    return !!fs.read(&out[0], size);
}

//单层路径创建
bool CPublicFunc::createDirForSingle(const std::string &sPath)
{
    if(sPath.empty()) return false;
#if defined(_WIN32) || defined(WIN32)
    std::wstring wsPath = strToWStr(sPath);
    DWORD ftyp = GetFileAttributes(wsPath.c_str());
    if (ftyp == INVALID_FILE_ATTRIBUTES)
    {
        // 路径不存在，创建目录
        if (CreateDirectory(wsPath.c_str(), NULL)) return true;
        else
        {
            std::cerr << "Failed to create directory!" << std::endl;
            return false;
        }
    }
    // 路径已存在且是一个目录
    else if (ftyp & FILE_ATTRIBUTE_DIRECTORY) return true;
    else
    {
        std::cerr << "Path exists but is not a directory!" << std::endl;
        return false;
    }
#elif defined(__linux__)
    struct stat info;

    // 检查目录是否已存在
    if (stat(sPath.c_str(), &info) != 0)
    {
        // 目录不存在，尝试创建
        if (mkdir(sPath.c_str(), 0777) == 0)  return true;
        else
        {
            std::cerr << "Failed to create directory!" << std::endl;
            return false;
        }
    }
    // 目录已存在
    else if (info.st_mode & S_IFDIR) return true;
    else
    {
        std::cerr << "Path exists but is not a directory!" << std::endl;
        return false;
    }
#else
#endif
}

//判断路径是否存在，不存在则创建
bool CPublicFunc::createDirectory(const std::string &sPath)
{
    std::vector<std::string> vecStr = stringSplit(sPath, "/", false);
    if(vecStr.empty())
    {
        vecStr = stringSplit(sPath, "\\");
    }
    if(vecStr.empty()) return createDirForSingle(sPath);
    std::string sTemp = vecStr.at(0);
    if(vecStr[0].empty()) sTemp = "/";
    if(false == createDirForSingle(sTemp)) return false;
    for(unsigned int i=1; i<vecStr.size(); ++i)
    {
        sTemp += "/";
        sTemp += vecStr.at(i);
        bool bRet = createDirForSingle(sTemp);
        if(false == bRet) return false;
    }
    return true;
}

//判断路径是否存在
bool CPublicFunc::pathExists(const std::string &sPath)
{
    if(sPath.empty()) return false;
#if defined(_WIN32) || defined(WIN32)
    std::wstring wsPath = strToWStr(sPath);
    DWORD ftyp = GetFileAttributes(wsPath.c_str());
    if (ftyp == INVALID_FILE_ATTRIBUTES) return false;
    // 路径已存在且是一个目录
    else if (ftyp & FILE_ATTRIBUTE_DIRECTORY) return true;
    else
    {
        std::cerr << "Path exists but is not a directory!" << std::endl;
        return false;
    }
#elif defined(__linux__)
    struct stat info;

    // 检查目录是否已存在
    if (stat(sPath.c_str(), &info) != 0) return false;
    // 目录已存在
    else if (info.st_mode & S_IFDIR) return true;
    else
    {
        std::cerr << "Path exists but is not a directory!" << std::endl;
        return false;
    }
#else
#endif
}


//判断路径是否存在
bool CPublicFunc::fileExists(const std::string &sFile)
{
    if(sFile.empty()) return false;
#if defined(_WIN32) || defined(WIN32)
    std::wstring wsPath = strToWStr(sFile);
    DWORD ftyp = GetFileAttributes(wsPath.c_str());
    // 路径不存在
    if (ftyp == INVALID_FILE_ATTRIBUTES) return false;
    // 目录存在
    else if (ftyp & FILE_ATTRIBUTE_DIRECTORY) return false;
    // 文件存在
    else return true;
#elif defined(__linux__)
    struct stat info;

    // 目录不存在
    if (stat(sFile.c_str(), &info) != 0) return false;
    // 目录存在
    else if (info.st_mode & S_IFDIR) return false;
    // 文件存在
    else return true;
#else
#endif
}

//使用时间戳+原始文件名保证唯一性
std::string CPublicFunc::generate_unique_filename(const std::string &original)
{
    std::string timestamp = getNowTime("%Y%m%d%H%M%S");
    return timestamp + "_" + original;
}

//获取当前时间，并转成字符串（只能精确到秒）
std::string CPublicFunc::getFormatTime(const std::string &sFormat)
{
    std::time_t nowT = std::time(0);
    std::tm *ltm = localtime(&nowT);
    char timeBuf[20];
    memset(timeBuf, 0, sizeof(timeBuf));
    std::strftime(timeBuf, sizeof(timeBuf), sFormat.c_str(), ltm);
    std::string sTime(timeBuf);
    return sTime;
}

//获取当前时间，并转成字符串
std::string CPublicFunc::getNowTime(const bool &bMSec)
{
    std::time_t nowT = std::time(0);
    std::tm *ltm = localtime(&nowT);
    char timeBuf[20];
    memset(timeBuf, 0, sizeof(timeBuf));
    //std::strftime(timeBuf, sizeof(timeBuf), "%Y-%m-%d %H:%M:%S", ltm);
    std::strftime(timeBuf, sizeof(timeBuf), "%F %X", ltm);
    std::string sTime(timeBuf);
    if(false == bMSec) return sTime;    //格式：yyyy-MM-dd hh:mm:ss
#if defined(_WIN32) || defined(WIN32)
    using namespace std::chrono;
    // 获取当前时间点（自 Unix 纪元以来）
    auto nowTime = system_clock::now();
    // 转换为自 Unix 纪元以来的毫秒数
    auto duration = nowTime.time_since_epoch();
    auto tStamp = duration_cast<milliseconds>(duration).count();
    int nMSec = tStamp  % 1000;
#elif defined(__linux__)
    timespec ts;
    if(-1 == clock_gettime(CLOCK_REALTIME, &ts)) return sTime;
    int nMSec = ts.tv_nsec / 1000000;
#else
#endif
    sTime += ":";
    std::ostringstream oss;
    oss << std::setfill('0') << std::setw(3) << nMSec;
    sTime += oss.str();
    return sTime;           //格式：yyyy-MM-dd hh:mm:ss:zzz
}

//字符串用字符分割(bEmpty:是否清理空字符串，true:清理(默认)，false:不清理)
VecStr CPublicFunc::stringSplit(const std::string &src, char sep, const bool &bEmpty)
{
    std::vector<std::string> vecStr;
    if(src.empty()) return vecStr;
    std::stringstream ss;
    ss << src;
    std::string str;
    while(std::getline(ss, str, sep))
    {
        if((false == bEmpty) || (bEmpty && (false == str.empty()))) vecStr.push_back(str);
    }
    return vecStr;
}

//字符串用字符串分割(bEmpty:是否清理空字符串，true:清理(默认)，false:不清理)
VecStr CPublicFunc::stringSplit(const std::string &src, const std::string &sep,
                                const bool &bEmpty)
{
    std::vector<std::string> vecStr;
    if(src.empty()) return vecStr;
    if(sep.empty())
    {
        vecStr.push_back(src);
        return vecStr;
    }

    int nLimitLen = sep.length();
    int nLimitIndex = 0;
    int nContentIndex = 0;
    while(1)
    {
        nLimitIndex = src.find(sep, nContentIndex);
        if(-1 == nLimitIndex) break;

        std::string str = src.substr(nContentIndex, nLimitIndex - nContentIndex);
        if((false == bEmpty) || (bEmpty && (false == str.empty()))) vecStr.push_back(str);
        nContentIndex += (nLimitIndex - nContentIndex) + nLimitLen;
    }
    std::string sEndStr = src.substr(nContentIndex);
    if((false == bEmpty) || (bEmpty && (false == sEndStr.empty()))) vecStr.push_back(sEndStr);
    return vecStr;
}

//std::string转std::wstring
std::wstring CPublicFunc::strToWStr(const std::string &str)
{
    std::wstring wstr(str.size(), L'\0');
    std::mbstowcs(&wstr[0], str.c_str(), str.size());
    return wstr;
}

//std::wstring转std::string
std::string CPublicFunc::wStrToStr(const std::wstring &wStr)
{
    std::string str;
    // 遍历宽字符字符串
    for (wchar_t wc : wStr)
    {
        // 计算当前字符的最大字节长度
        size_t len = std::wcrtomb(nullptr, wc, nullptr);
        if (len == (size_t)-1)
        {
            // 错误处理：如果转换失败
            std::cerr << "Character conversion failed" << std::endl;
            return "";
        }
        // 创建一个足够大的缓冲区来存储转换结果
        std::vector<char> mb(len + 1);  // 多分配一个字节给 '\0'
        std::wcrtomb(mb.data(), wc, nullptr);
        // 追加到目标字符串
        str.append(mb.data(), len);
    }
    return str;
}

//遍历目录查询结果
#if defined(_WIN32) || defined(WIN32)
void CPublicFunc::walkDirectory(const std::string& root, const std::string& target_ext,
                                std::vector<std::string>& results, const bool &bPath)
{
    WIN32_FIND_DATA ffd;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    std::string sCurPath = root;
    if((sCurPath.back() != '\\') &&
            (sCurPath.back() != '/')) sCurPath += "/";
    std::string search_path = sCurPath + "*";
    hFind = FindFirstFile(strToWStr(search_path).c_str(), &ffd);
    if (hFind == INVALID_HANDLE_VALUE)
    {
        std::wcout << L"walk directory file path is invalid. file path: " << strToWStr(search_path) << std::endl;
        return;
    }
    do {
        const std::string name = wStrToStr(ffd.cFileName);
        if (name == "." || name == "..") continue;

        const std::string full_path = sCurPath + name;
        if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) walkDirectory(full_path, target_ext, results, bPath);
        else
        {
            const std::string ext = toLower(full_path.substr(full_path.find_last_of(".") + 1));
            if (ext == target_ext && bPath) results.push_back(full_path);
            else if(ext == target_ext)
            {
                // 提取文件名，不带路径和扩展名
                size_t last_dot_pos = full_path.find_last_of(".");
                size_t last_slash_pos = full_path.find_last_of("\\");
                std::string filename = full_path.substr(last_slash_pos + 1, last_dot_pos - last_slash_pos - 1);
                results.push_back(filename);  // 将文件名添加到结果列表
            }
        }
    } while (FindNextFile(hFind, &ffd) != 0);
    FindClose(hFind);
}
#elif defined(__linux__)
void CPublicFunc::walkDirectory(const std::string& root, const std::string& target_ext,
                                std::vector<std::string>& results, const bool& bPath)
{
    DIR* dir;
    struct dirent* ent;
    struct stat st{};

    if ((dir = opendir(root.c_str())) == nullptr) return;

    while ((ent = readdir(dir)) != nullptr) {
        const std::string name = ent->d_name;
        if (name == "." || name == "..") continue;

        const std::string full_path = root + name;

        if (stat(full_path.c_str(), &st) == -1) continue;

        if (S_ISDIR(st.st_mode)) walkDirectory(full_path, target_ext, results, bPath);
        else
        {
            const size_t dot_pos = full_path.find_last_of('.');
            if (dot_pos != std::string::npos) {
                const std::string ext = toLower(
                            full_path.substr(dot_pos + 1));
                if (ext == target_ext && bPath) results.push_back(full_path);
                else if(ext == target_ext)
                {
                    // 提取文件名，不带路径和扩展名
                    size_t last_slash_pos = full_path.find_last_of('/');
                    std::string filename = full_path.substr(last_slash_pos + 1, dot_pos - last_slash_pos - 1);
                    results.push_back(filename);  // 将文件名添加到结果列表
                }
            }
        }
    }
    closedir(dir);
}
#else
#endif

//通用工具函数：小写转换
std::string CPublicFunc::toLower(const std::string &str)
{
    std::string lower_str = str;
    std::transform(lower_str.begin(), lower_str.end(), lower_str.begin(),
                   [](char c) { return std::tolower(static_cast<unsigned char>(c)); });
    return lower_str;
}

//通过文件扩展名，发现文件
VecStr CPublicFunc::findFiles(const std::string &sPath, const std::string &targetExt, bool bPath)
{
    std::vector<std::string> results;
    const std::string clean_ext = toLower(targetExt.substr(targetExt.find_last_of('.') + 1));
    walkDirectory(sPath, clean_ext, results, bPath);
    return results;
}

//获取运行目录
std::string CPublicFunc::currentPath()
{
#if defined(_WIN32) || defined(WIN32)
    wchar_t wpath[MAX_PATH];
    if (0 == GetModuleFileName(nullptr, wpath, MAX_PATH)) return "";
    std::wstring wfullPath(wpath);
    //路径输出
    std::string fullPath = wStrToStr(wfullPath);
    size_t pos = fullPath.find_last_of("\\/");
    if (pos != std::string::npos) {
        fullPath = fullPath.substr(0, pos); // 获取目录路径
    }
    return fullPath;
#elif defined(__linux__)
    char buffer[PATH_MAX];
    ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1);
    if (-1 == len) return "";
    buffer[len] = '\0';
    std::string fullPath(buffer);
    size_t pos = fullPath.find_last_of("/\\");
    if (pos != std::string::npos) {
        fullPath = fullPath.substr(0, pos); // 获取目录路径
    }
    return fullPath;
#else
#endif
}

//获取文件所有数据
std::string CPublicFunc::getFileAllData(const std::string &sFile, std::string &sErrMsg, bool bBinary)
{
    sErrMsg = "";
    std::ifstream ifs;
    //打开文件
    if(bBinary) ifs = std::ifstream(sFile, std::ios::binary);
    else ifs = std::ifstream(sFile, std::ios::in);
    if(false == ifs.is_open())
    {
        sErrMsg = getErrMsg(enFileOpenFailed);
        return "";
    }
    //获取文件大小
    ifs.seekg(0, std::ios::end);
    size_t nSize = ifs.tellg();
    ifs.seekg(0, std::ios::beg);
    //读取数据到缓冲区
    std::vector<char> vecCh(nSize);
    ifs.read(vecCh.data(), nSize);
    std::string sData(vecCh.begin(), vecCh.end());
    return sData;
}

//获取文件名称（不带路径和后缀）
std::string CPublicFunc::fileName(const std::string &sFile)
{
    // 提取文件名，不带路径和扩展名
    size_t lastDotPos = sFile.find_last_of(".");
    if(lastDotPos == std::string::npos) lastDotPos = 0;
    size_t lastSlashPos1 = sFile.find_last_of("\\");
    if(lastSlashPos1 == std::string::npos) lastSlashPos1 = 0;
    size_t lastSlashPos2 = sFile.find_last_of("/");
    if(lastSlashPos2 == std::string::npos) lastSlashPos2 = 0;
    size_t lastSlashPos = max(lastSlashPos1, lastSlashPos2);
    std::string sName = sFile.substr(lastSlashPos + 1, lastDotPos - lastSlashPos - 1);
    return sName;
}

//获取文件行数(默认以换行符计算，bSimple==false,逐字符解析，处理引号和转义逻辑)
int CPublicFunc::fileLines(const std::string &sFile, bool bSimple)
{
    std::ifstream file(sFile);
    if (!file.is_open()) {
        std::cerr << "无法打开文件: " << sFile << std::endl;
        return -1;
    }
    //以换行符计算行数
    if(bSimple)
    {
        int count = 0;
        std::string line;
        while (std::getline(file, line)) {
            ++count;
        }
        return count;
    }

    //逐字符解析，处理引号和转义逻辑
    int line_count = 0;
    bool in_quotes = false;
    bool current_line_has_data = false;
    char ch;
    bool prev_was_quote = false;

    //逐字符读取解析
    while (file.get(ch))
    {
        if (ch == '"')
        {
            //引号判断
            if (prev_was_quote)
            {
                prev_was_quote = false;
                current_line_has_data = true;
            }
            else prev_was_quote = true;
            if (!prev_was_quote) in_quotes = !in_quotes;
        }
        else
        {
            if (prev_was_quote)
            {
                in_quotes = !in_quotes;
                prev_was_quote = false;
            }
            if (ch == '\n')
            {
                //判断是否在引号内
                if (!in_quotes)
                {
                    line_count++;
                    current_line_has_data = false;
                }
                else current_line_has_data = true;
            }
            else current_line_has_data = true;
        }
    }
    //尾行处理
    if (prev_was_quote) in_quotes = !in_quotes;
    if (!in_quotes && current_line_has_data) line_count++;
    return line_count;
}

//获取排序类型
int CPublicFunc::getOrder(const std::string &sOrder)
{
    std::string str = toLower(sOrder);
    if("asc" == str) return enAsc;
    return enDesc;
}

//16进制显示字符串
std::string CPublicFunc::toStrHex(const std::string &str)
{
    std::stringstream ss;
    ss << std::hex << std::setfill('0');

    for (unsigned char c : str) {
        ss << std::setw(2) << static_cast<int>(c);
    }

    return ss.str();
}
//转16进制显示
std::string CPublicFunc::toU16Hex(const uint16_t &value)
{
    std::stringstream ss;
    ss << "0x" << std::hex << std::setw(4)
       << std::setfill('0') << value;
    return ss.str();
}

//转16进制显示
std::string CPublicFunc::toU32Hex(const uint32_t &value)
{
    std::stringstream ss;
    ss << "0x" << std::hex << std::setw(8)
       << std::setfill('0') << value;
    return ss.str();
}

//反转一个字节 (8位)
uint8_t CPublicFunc::reflect8Bits(uint8_t byte)
{
    byte = ((byte & 0xF0) >> 4) | ((byte & 0x0F) << 4);
    byte = ((byte & 0xCC) >> 2) | ((byte & 0x33) << 2);
    byte = ((byte & 0xAA) >> 1) | ((byte & 0x55) << 1);
    return byte;
}

//反转16位数据
uint16_t CPublicFunc::reflect16Bits(uint16_t value)
{
    value = ((value & 0xFF00) >> 8) | ((value & 0x00FF) << 8);
    value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
    value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
    value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
    return value;
}

//
uint32_t CPublicFunc::reflect32Bits(uint32_t value)
{
    // 输出数据反转
    value = (value & 0x55555555) << 1 | (value & 0xAAAAAAAA) >> 1;
    value = (value & 0x33333333) << 2 | (value & 0xCCCCCCCC) >> 2;
    value = (value & 0x0F0F0F0F) << 4 | (value & 0xF0F0F0F0) >> 4;
    value = (value & 0x00FF00FF) << 8 | (value & 0xFF00FF00) >> 8;
    value = (value & 0x0000FFFF) << 16 | (value & 0xFFFF0000) >> 16;
    return value;
}

//CRC16
uint16_t CPublicFunc::crc16ForVec(const std::vector<uint8_t> &vec, CCRC16Info info)
{
    uint16_t crc = info.nInit;  // 初始值
    const uint16_t polynomial = info.nPoly;  // 多项式
    for (uint8_t byte : vec)
    {
        // 输入数据反转 (bit reflection)
        if(1 == info.nRefIn) byte = reflect8Bits(byte);
        crc ^= (static_cast<uint16_t>(byte) << 8);
        for (int j = 0; j < 8; ++j)
        {
            if (crc & 0x8000) crc = (crc << 1) ^ polynomial;
            else crc <<= 1;
        }
    }
    // 输出数据反转 (bit reflection)
    if(1 == info.nRefOut) crc = reflect16Bits(crc);
    //结果异或值
    crc ^= info.nXorOut;
    return crc;
}

//CRC16
uint16_t CPublicFunc::crc16ForString(const std::string &str, CCRC16Info info)
{
    std::vector<uint8_t> vec(str.begin(), str.end());
    uint16_t crc = info.nInit;  // 初始化CRC寄存器
    crc = crc16ForVec(vec, info);
    return crc;
}

//CRC32校验
uint32_t CPublicFunc::crc32ForVec(const std::vector<uint8_t> &vec, CCRC32Info info)
{
    uint32_t crc = info.nInit;  // 初始值
    const uint32_t polynomial = info.nPoly;  // 多项式
    for (uint8_t byte : vec)
    {
        // 输入数据反转
        if(1 == info.nRefIn) byte = reflect8Bits(byte);
        crc ^= (static_cast<uint32_t>(byte) << 24);
        for (int i = 0; i < 8; ++i)
        {
            if (crc & 0x80000000) crc = (crc << 1) ^ polynomial;
            else crc <<= 1;
        }
    }
    // 输出数据反转 (bit reflection)
    if(1 == info.nRefOut) crc = reflect32Bits(crc);
    // 结果异或值
    crc ^= info.nXorOut;
    return crc;
}

//CRC32校验
uint32_t CPublicFunc::crc32ForString(const std::string &str, CCRC32Info info)
{
    std::vector<uint8_t> vec(str.begin(), str.end());
    uint32_t crc = info.nInit;
    crc = crc32ForVec(vec, info);
    return crc;
}


}   //end namespace PubFunc
